﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace ArkanoidX
{
    public class StatefulComponent : Microsoft.Xna.Framework.DrawableGameComponent
    {
        public abstract class State<ObjT>
        {
            // Sprite texture, read-only property
            public Texture2D Texture { get { return _texture; } }

            // Sprite size in pixels
            public Vector2 Size { get { return _size; } }

            public virtual Vector2 HalfSize { get { return _size / 2; } }

            // Rectangle in the texture
            public Rectangle RegionInSource { get { return _regionInSource; } }

            protected Texture2D _texture;
            protected Rectangle _regionInSource;
            protected Vector2 _size;
            protected Vector2 _halfSize;
            protected Vector2 _srcHalfSize;
            protected Rectangle _rectInTarget;  // buffered value representing !!! SHARED BY METHODS !!!


            public State(Texture2D texture, Vector2 size, Rectangle regionInSource)
            {
                _texture = texture;
                _size = size;
                _regionInSource = regionInSource;

                _halfSize = new Vector2(_size.X / 2, _size.Y / 2);
                _rectInTarget = new Rectangle(0, 0, (int)(_size.X + 0.5f), (int)(_size.Y + 0.5f));

                _srcHalfSize = new Vector2(regionInSource.Width / 2, regionInSource.Y / 2);
            }

            public State(Texture2D texture, Vector2 size)
                : this(texture, size, new Rectangle(0, 0, texture.Width, texture.Height))
            {
            }

            public State(Texture2D texture)
                : this(texture, new Vector2(texture.Width, texture.Height),
                       new Rectangle(0, 0, texture.Width, texture.Height))
            {
            }

            public virtual void Draw(SpriteBatch sBatch, Vector2 position, Color color)
            {
                // draw the sprite at specific position onto the batch
                position -= _halfSize;
                _rectInTarget.X = (int)Math.Round(position.X);
                _rectInTarget.Y = (int)Math.Round(position.Y);

                sBatch.Draw(_texture, _rectInTarget, _regionInSource, color);
            }

            public virtual void Draw(SpriteBatch sBatch, Vector2 position, Color color, float angle)
            {
                // draw the sprite at specific position onto the batch
                _rectInTarget.X = (int)Math.Round(position.X);
                _rectInTarget.Y = (int)Math.Round(position.Y - _halfSize.Y);

                sBatch.Draw(_texture, _rectInTarget, _regionInSource, color, angle, _srcHalfSize,
                       SpriteEffects.None, 0);
            }

            // Do update according to the state of the object
            public abstract void Update(ObjT obj, GameTime gameTime);

        }

        public StatefulComponent(Game game)
            : base(game)
        {
        }
    }

}
